package com.logistic.server.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.logistic.server.common.constant.Constants;
import com.logistic.server.common.exception.BaseException;
import com.logistic.server.common.utils.DictUtils;
import com.logistic.server.common.utils.SecurityUtils;
import com.logistic.server.entity.common.PageRequest;
import com.logistic.server.entity.common.PageResponse;
import com.logistic.server.entity.pojo.SysDictData;
import com.logistic.server.entity.pojo.SysDictType;
import com.logistic.server.mapper.SysDictDataMapper;
import com.logistic.server.mapper.SysDictTypeMapper;
import com.logistic.server.service.ISysDictTypeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 字典类型 服务实现类
 * </p>
 *
 * @author swen
 * @since 2021-10-25
 */
@Service
@Transactional
public class SysDictTypeServiceImpl extends ServiceImpl<SysDictTypeMapper, SysDictType> implements ISysDictTypeService {

    @Resource
    private DictUtils dictUtils;

    @Resource
    private SysDictDataMapper dictDataMapper;

    /**
     * 字典类型列表
     * @param dictType 字典类型
     * @param pageRequest 分页参数
     * @return list
     */
    @Override
    public PageResponse<SysDictType> selectPageDictTypeList(SysDictType dictType, PageRequest pageRequest) {
        Map<String, Object> params = dictType.getParams();
        LambdaQueryWrapper<SysDictType> queryWrapper = new LambdaQueryWrapper<SysDictType>()
                .like(StrUtil.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
                .eq(StrUtil.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
                .like(StrUtil.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
                .apply(ObjectUtil.isNotEmpty(params.get("beginTime")),
                        "date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
                        params.get("beginTime"))
                .apply(ObjectUtil.isNotEmpty(params.get("endTime")),
                        "date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
                        params.get("endTime"));
        IPage<SysDictType> page = new Page<>(pageRequest.getPageIndex(), pageRequest.getPageSize());
        IPage<SysDictType> result = baseMapper.selectPage(page,  queryWrapper);
        return PageResponse.<SysDictType>builder().list(result.getRecords()).total(result.getTotal()).build();
    }

    /**
     * 新增字典类型
     * @param dictType 字典类型
     */
    @Override
    public void insertDictType(SysDictType dictType) {
        if (Constants.NOT_UNIQUE.equals(this.checkDictTypeUnique(dictType))) {
            throw new BaseException("新增字典'" + dictType.getDictName() + "'失败，字典类型已存在");
        }
        dictType.setCreateBy(SecurityUtils.getUsername());
        dictType.setCreateTime(new Date());
        baseMapper.insert(dictType);
        dictUtils.setDictCache(dictType.getDictType(), null);
    }

    /**
     * 校验字典类型称是否唯一
     *
     * @param dict 字典类型
     * @return 结果
     */
    @Override
    public String checkDictTypeUnique(SysDictType dict) {
        long dictId = ObjectUtil.isNull(dict.getDictId()) ? -1L : dict.getDictId();
        SysDictType dictType = getOne(new LambdaQueryWrapper<SysDictType>()
                .eq(SysDictType::getDictType, dict.getDictType())
                .last("limit 1"));
        if (ObjectUtil.isNotNull(dictType) && dictType.getDictId() != dictId) {
            return Constants.NOT_UNIQUE;
        }
        return Constants.UNIQUE;
    }

    /**
     * 修改字典类型
     * @param dictType 字典类型
     */
    @Override
    public void updateDictType(SysDictType dictType) {
        if (Constants.NOT_UNIQUE.equals(this.checkDictTypeUnique(dictType))) {
            throw new BaseException("修改字典类型'" + dictType.getDictName() + "'失败，字典类型已存在");
        }
        SysDictType oldDict = getById(dictType.getDictId());
        dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>()
                .set(SysDictData::getDictType, dictType.getDictType())
                .eq(SysDictData::getDictType, oldDict.getDictType()));
        baseMapper.updateById(dictType);
        List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
        dictUtils.setDictCache(dictType.getDictType(), dictDatas);
    }

    /**
     * 根据字典类型ID查询信息
     *
     * @param dictId 字典类型ID
     * @return 字典类型
     */
    @Override
    public SysDictType selectDictTypeById(Long dictId) {
        return getById(dictId);
    }

    /**
     * 删除字典类型
     * @param ids ids
     */
    @Override
    public void deleteDictTypeByIds(Long[] ids) {
        for (Long dictId : ids) {
            SysDictType dictType = selectDictTypeById(dictId);
            if (dictDataMapper.selectCount(new LambdaQueryWrapper<SysDictData>()
                    .eq(SysDictData::getDictType, dictType.getDictType())) > 0) {
                throw new BaseException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
            }
            dictUtils.removeDictCache(dictType.getDictType());
        }
        baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 刷新缓存
     */
    @Override
    public void resetDictCache() {
        clearDictCache();
        loadingDictCache();
    }

    /**
     * 加载字典缓存数据
     */
    @Override
    public void loadingDictCache() {
        List<SysDictType> dictTypeList = list();
        for (SysDictType dictType : dictTypeList) {
            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
            dictUtils.setDictCache(dictType.getDictType(), dictDatas);
        }
    }

    /**
     * 清空字典缓存数据
     */
    @Override
    public void clearDictCache() {
        dictUtils.clearDictCache();
    }

    /**
     * 获取字典类型下拉
     * @return list
     */
    @Override
    public List<SysDictType> selectDictTypeAll() {
        return list();
    }
}
